For most small games, you’ll be spending all your time in the Game1.cs file. The Game1 class derives from Game and in its pristine state it defines two fields: graphicsspriteBatch. and To those two fields I want to add three more:
Example 2. XNA Project: XnaHelloPhone File: Game1.cs (excerpt showing fields)
namespace XnaHelloPhone { public class Game1 : Microsoft.Xna.Framework.Game { GraphicsDeviceManager graphics; SpriteBatch spriteBatch; string text = "Hello, Windows Phone 7!"; SpriteFont segoe14; Vector2 textPosition; . . . } }
|
These three new fields simply indicate the text that the program
will display, the font it will use to display it, and the position of
the text on the screen. That position is specified in pixel coordinates
relative to the upper-left corner of the display. The Vector2 structure has two fields named X and Y of type float. For performance purposes, all floating-point values in XNA are single-precision. (Silverlight is all double-precision.) The Vector2 structure is often used for two-dimensional points, sizes, and even vectors.
When the game is run on the phone, the Game1 class is instantiated and the Game1 constructor is executed. This standard code is provided for you:
Example 3. XNA Project: XnaHelloPhone File: Game1.cs (excerpt)
public Game1() { graphics = new GraphicsDeviceManager(this); Content.RootDirectory = "Content";
// Frame rate is 30 fps by default for Windows Phone. TargetElapsedTime = TimeSpan.FromTicks(333333); }
|
The first statement initializes the graphics field. In the second statement, Content is a property of Game of type ContentManager, and RootDirectory is a property of that class. Setting this property to “Content”
is consistent with the Content directory that is currently storing the
14-point Segoe font. The third statement sets a time for the program’s
game loop, which governs the pace at which the program updates the
video display. The Windows Phone 7 screen is refreshed at 30 frames per
second.
After Game1 is instantiated, a Run method is called on the Game1 instance, and the base Game class initiates the process of starting up the game. One of the first steps is a call to the Initialize method, which a Game derivative can override. XNA Game Studio generates a skeleton method to which I won’t add anything:
Example 4. XNA Project: XnaHelloPhone File: Game1.cs (excerpt)
protected override void Initialize() { base.Initialize(); }
|
The Initialize method is not the place to load the font or other content. That comes a little later when the base class calls the LoadContent method.
Example 5. XNA Project: XnaHelloPhone File: Game1.cs (excerpt)
protected override void LoadContent() { spriteBatch = new SpriteBatch(GraphicsDevice);
segoe14 = this.Content.Load<SpriteFont>("Segoe14"); Vector2 textSize = segoe14.MeasureString(text); Viewport viewport = this.GraphicsDevice.Viewport;
textPosition = new Vector2((viewport.Width - textSize.X) / 2, (viewport.Height - textSize.Y) / 2); }
|
The first statement in this method is provided for you. You’ll see shortly how this spriteBatch object is used to shoot sprites out to the display.
The other statements are ones I’ve added, and you’ll notice I tend to preface property names like Content and GraphicsDevice with the keyword this to remind myself that they’re properties and not a static class. As I mentioned, the Content property is of type ContentManager. The generic Load method allows loading content into the program, in this case content of type SpriteFont.
The name in quotation marks is the Asset Name as indicated in the
content’s properties. This statement stores the loaded font in the segoe14 field of type SpriteFont.
In XNA, sprites
(including text strings) are usually displayed by specifying the pixel
coordinates relative to the upper-left corner or the sprite relative to
the upper-left corner of the display. To calculate these coordinates,
it’s helpful to know both the screen size and the size of the text when
displayed with a particular font.
The SpriteFont class has a very handy method named MeasureString that returns a Vector2
object with the size of a particular text string in pixels. (For the
14-point Segoe UI Mono font, which has an equivalent height of 18-2/3
pixels, the MeasureString call returns a height of 28 pixels.)
An XNA program generally uses the Viewport property of the GraphicsDevice class to obtain the size of the screen. This is accessible through the GraphicsDeviceGame and provides Width and Height properties. property of
It is then straightforward to calculate textPosition—the point relative to the upper-left corner of the viewport where the upper-left corner of the text string is to be displayed.
The initialization phase of the program has now concluded, and the real action begins. The program enters the game loop. In synchronization with the 30 frame-per-second refresh rate of the video display, two methods in your program are called: Update followed by Draw. Back and forth: Update, Draw, Update, Draw, Update, Draw…. (It’s actually somewhat more complicated than this if the Update method requires more than 1/30th of a second to complete.